package com.ljf.daily.makemoneysoftware.domain.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ljf.common.domain.service.BasisDomainService;
import com.ljf.common.exception.ServiceException;
import com.ljf.common.utils.CollectionUtil;
import com.ljf.common.utils.EnumUtil;
import com.ljf.daily.makemoneysoftware.domain.repository.DailyDatMakeMoneySoftwareConfigRepository;
import com.ljf.daily.makemoneysoftware.domain.repository.DailyDatMakeMoneySoftwareRepository;
import com.ljf.daily.makemoneysoftware.dto.command.DailyDatMakeMoneySoftwareCommand;
import com.ljf.daily.makemoneysoftware.dto.command.DailyDatMakeMoneySoftwareConfigCommand;
import com.ljf.daily.makemoneysoftware.dto.query.DailyDatMakeMoneySoftwareConfigQuery;
import com.ljf.daily.makemoneysoftware.dto.query.DailyDatMakeMoneySoftwareQuery;
import com.ljf.daily.makemoneysoftware.enums.DailyDatMakeMoneySoftwareConfigAccountLimitModeEnum;
import com.ljf.daily.makemoneysoftware.enums.DailyDatMakeMoneySoftwareConfigAccountModeEnum;
import com.ljf.daily.makemoneysoftware.enums.DailyDatMakeMoneySoftwareConfigExecuteEnum;
import com.ljf.daily.makemoneysoftware.model.DailyDatMakeMoneySoftware;
import com.ljf.daily.makemoneysoftware.model.DailyDatMakeMoneySoftwareConfig;
import com.ljf.daily.makemoneysoftware.vo.DailyDatMakeMoneySoftwareConfigVO;
import com.ljf.daily.makemoneysoftware.vo.DailyDatMakeMoneySoftwareVO;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 赚钱软件定义  领域服务
 *
 * @author LJF
 * @since 2024-02-26
 */
@Component
@AllArgsConstructor
public class DailyDatMakeMoneySoftwareDomainService extends BasisDomainService<DailyDatMakeMoneySoftwareRepository, DailyDatMakeMoneySoftwareQuery, DailyDatMakeMoneySoftwareVO, DailyDatMakeMoneySoftware, DailyDatMakeMoneySoftwareCommand> {

    private final DailyDatMakeMoneySoftwareConfigRepository configRepository;

    /**
     * 更新配置
     *
     * @param command
     * @throws ServiceException
     */
    public void editConfig(DailyDatMakeMoneySoftwareConfigCommand command) throws ServiceException {
        DailyDatMakeMoneySoftwareConfigAccountModeEnum accountModeEnum = EnumUtil.getEnumByCode(
                command.getAccountMode(), DailyDatMakeMoneySoftwareConfigAccountModeEnum.values()
        );
        if (accountModeEnum == null) {
            throw new ServiceException("校验异常: 记账模式异常");
        }
        boolean fillLimitNum = false;
        if (Boolean.TRUE.equals(accountModeEnum.getAccountLimit())) {
            fillLimitNum = Objects.equals(
                    command.getAccountLimitMode(),
                    DailyDatMakeMoneySoftwareConfigAccountLimitModeEnum.LIMIT_NUMBER.getCode()
            );
        }
        DailyDatMakeMoneySoftwareConfig model = DailyDatMakeMoneySoftwareConfig.builder()
                .code(command.getCode())
                .executeInsert(command.getExecuteInsert())
                .executeImport(command.getExecuteImport())
                .executeTemplate(command.getExecuteTemplate())
                .executeDelete(command.getExecuteDelete())
                .executeConsumption(command.getExecuteConsumption())
                .executeCostWithhold(command.getExecuteCostWithhold())
                .executeCostWithholdLeveling(command.getExecuteCostWithholdLeveling())
                .executeCostConsume(command.getExecuteCostConsume())
                .executeCostConsumeLeveling(command.getExecuteCostConsumeLeveling())
                .executeCostDifference(command.getExecuteCostDifference())
                .executeCostDifferenceLeveling(command.getExecuteCostDifferenceLeveling())
                .accountMode(command.getAccountMode())
                .accountLimitMode(Boolean.TRUE.equals(accountModeEnum.getAccountLimit()) ? command.getAccountLimitMode() : 0)
                .limitNum(fillLimitNum ? command.getLimitNum() : 0)
                .build();
        List<DailyDatMakeMoneySoftwareConfigVO> configList = configRepository.selectList(
                DailyDatMakeMoneySoftwareConfigQuery.builder().code(command.getCode()).build()
        );
        if (CollectionUtil.isEmpty(configList)) {
            configRepository.insert(model);
        }
        else {
            model.setId(configList.get(0).getId());
            configRepository.updateById(model);
        }
    }

    /**
     * 配置分页查询
     *
     * @param query
     * @return
     * @throws ServiceException
     */
    public Page<DailyDatMakeMoneySoftwareConfigVO> queryConfig(DailyDatMakeMoneySoftwareQuery query) throws ServiceException {
        Page<DailyDatMakeMoneySoftwareConfigVO> resultPage = new Page<>();
        Page<DailyDatMakeMoneySoftwareVO> subjectPage = query(query);
        resultPage.setTotal(subjectPage.getTotal());
        if (CollectionUtil.isNotEmpty(subjectPage.getRecords())) {
            List<String> codeList = subjectPage.getRecords()
                    .stream().map(DailyDatMakeMoneySoftwareVO::getCode).distinct().collect(Collectors.toList());
            List<DailyDatMakeMoneySoftwareConfigVO> configList = configRepository.selectList(
                    DailyDatMakeMoneySoftwareConfigQuery.builder().codeList(codeList).build()
            );
            Map<String, DailyDatMakeMoneySoftwareConfigVO> configMap = configList.stream().collect(
                    Collectors.toMap(DailyDatMakeMoneySoftwareConfigVO::getCode, Function.identity(), (a, b) -> a)
            );
            List<DailyDatMakeMoneySoftwareConfigVO> resultList = new ArrayList<>();
            DailyDatMakeMoneySoftwareConfigVO result;
            for (DailyDatMakeMoneySoftwareVO moneySoftware : subjectPage.getRecords()) {
                result = configMap.getOrDefault(moneySoftware.getCode(), new DailyDatMakeMoneySoftwareConfigVO());
                result.setCode(moneySoftware.getCode());
                result.setName(moneySoftware.getName());
                resultList.add(result);
            }
            resultPage.setRecords(resultList);
        }
        return resultPage;
    }

    /**
     * 直接记账查询
     *
     * @param query
     * @return
     * @throws ServiceException
     */
    public List<DailyDatMakeMoneySoftwareVO> queryListExecuteInsert(DailyDatMakeMoneySoftwareQuery query) throws ServiceException {
        List<DailyDatMakeMoneySoftwareConfigVO> configList = configRepository.selectList(
                conversionConfigQuery(query, "execute_insert")
        );
        List<String> codeList = configList.stream()
                .map(DailyDatMakeMoneySoftwareConfigVO::getCode).distinct().collect(Collectors.toList());
        return repository.selectList(
                DailyDatMakeMoneySoftwareQuery.builder()
                        .codeList(codeList)
                        .accountCode(query.getAccountCode())
                        .build()
        );
    }

    /**
     * 转化配置查询条件
     *
     * @param query
     * @return
     */
    private DailyDatMakeMoneySoftwareConfigQuery conversionConfigQuery(DailyDatMakeMoneySoftwareQuery query, String type) {
        DailyDatMakeMoneySoftwareConfigQuery configQuery = DailyDatMakeMoneySoftwareConfigQuery.builder()
                .code(query.getCode())
                .codeList(query.getCodeList())
                .build();
        if ("execute_insert".equals(type)) {
            configQuery.setExecuteInsert(DailyDatMakeMoneySoftwareConfigExecuteEnum.EXECUTE.getCode());
        }
        return configQuery;
    }

}
